﻿using System;
using GeoAPI.Geometries;
using YJKGridTopologyCal.Algorithm.Locate;
using YJKGridTopologyCal.Noding;
using YJKGridTopologyCal.Operation.Predicate;

namespace YJKGridTopologyCal.Geometries.Prepared
{
	public class PreparedPolygon : BasicPreparedGeometry
	{
		public PreparedPolygon(IPolygonal poly) : base((IGeometry)poly)
		{
			this._isRectangle = base.Geometry.IsRectangle;
		}

		public FastSegmentSetIntersectionFinder IntersectionFinder
		{
			get
			{
				if (this._segIntFinder == null)
				{
					object lockSif = this._lockSif;
					lock (lockSif)
					{
						if (this._segIntFinder == null)
						{
                            this._segIntFinder = new FastSegmentSetIntersectionFinder(SegmentStringUtil.ExtractSegmentStrings(base.Geometry));
						}
					}
				}
				return this._segIntFinder;
			}
		}

		public IPointOnGeometryLocator PointLocator
		{
			get
			{
				if (this._pia == null)
				{
					object lockPia = this._lockPia;
					lock (lockPia)
					{
						if (this._pia == null)
						{
							this._pia = new IndexedPointInAreaLocator(base.Geometry);
						}
					}
				}
				return this._pia;
			}
		}

		public override bool Intersects(IGeometry g)
		{
			if (!base.EnvelopesIntersect(g))
			{
				return false;
			}
			if (this._isRectangle)
			{
				return RectangleIntersects.Intersects((IPolygon)base.Geometry, g);
			}
			return PreparedPolygonIntersects.Intersects(this, g);
		}

		public override bool Contains(IGeometry g)
		{
			if (!base.EnvelopeCovers(g))
			{
				return false;
			}
			if (this._isRectangle)
			{
				return RectangleContains.Contains((IPolygon)base.Geometry, g);
			}
			return PreparedPolygonContains.Contains(this, g);
		}

		public override bool ContainsProperly(IGeometry g)
		{
			return base.EnvelopeCovers(g) && PreparedPolygonContainsProperly.ContainsProperly(this, g);
		}

		public override bool Covers(IGeometry g)
		{
			return base.EnvelopeCovers(g) && (this._isRectangle || PreparedPolygonCovers.Covers(this, g));
		}

		private readonly bool _isRectangle;

		private readonly object _lockSif = new object();

		private readonly object _lockPia = new object();

		private volatile FastSegmentSetIntersectionFinder _segIntFinder;

		private volatile IPointOnGeometryLocator _pia;
	}
}
